﻿using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace Chisel.Core.Connections
{
	/// <summary>
	/// Possible artities of a connection end point.
	/// </summary>
	public enum Arity { One, ZeroToOne, ZeroToMany, OneToMany }

	/// <summary>
	/// Provides decorators for a connection.
	/// </summary>
	public class DecorationProvider
	{

		#region Registry

		/// <summary>
		/// Contains all providers available at runtime.
		/// </summary>
		private static Dictionary<string, DecorationProvider> _providers = new Dictionary<string, DecorationProvider>();

		/// <summary>
		/// Registers a provider to be used by referencing the given id.
		/// </summary>
		public static void Register(string id, DecorationProvider provider)
		{
			_providers[id] = provider;
		}

		/// <summary>
		/// Gets the provider with the given id.
		/// </summary>
		public DecorationProvider Get(string id)
		{
			DecorationProvider provider;
			if (_providers.TryGetValue(id, out provider))
				return provider;
			return null;
		}


		/// <summary>
		/// Registers all decorator providers that come with Chisel.
		/// </summary>
		/// <remarks>This should be good for most applications. If not, custom providers must
		/// be registered manually.</remarks>
		public static void RegisterDefaults()
		{

		}

		#endregion


		#region Decorators

		private Dictionary<Arity, Type> _types = new Dictionary<Arity, Type>();

		/// <summary>
		/// Assigns the given decorator type to the given arity.
		/// </summary>
		/// <param name="arity">The arity to associate this type with.</param>
		/// <param name="type">A type that derives from Decorator.</param>
		public void AssignDecorator(Arity arity, Type type)
		{
			if (!type.IsSubclassOf(typeof(Decorator)))
				throw new Exception(type.ToString() + " is not a subclass of Chisel.Connections.Decorator.");
			_types[arity] = type;
		}

		/// <summary>
		/// Gets the decorator associated with the given arity.
		/// </summary>
		/// <remarks>If there isn't a decorator assigned to this arity, uses the one for Arity.One.</remarks>
		public Decorator GetDecorator(Arity arity)
		{
			// get the type of the decorator to create
			Type type = null;
			if (_types.ContainsKey(arity))
				type = _types[arity];
			else if (_types.ContainsKey(Arity.One))
				type = _types[Arity.One];
			else
				throw new Exception("This decorator provider has no decorator for arity " + arity.ToString());

			// create the decorator instance
			return Activator.CreateInstance(type) as Decorator;
		}

		#endregion


	}
}
